//////////////////////////////////////////////////////////////////////////////////////
// Desciption:
//     Utility functions
//
// Legal Notices:
//     Copyright (c) 2008, Telliam Consulting, LLC.
//     All rights reserved.
//
//     Redistribution and use in source and binary forms, with or without modification,
//     are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//
//     * Neither the name of Telliam Consulting nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// Disclaimer:
//     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//     IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
//     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
//     OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
//     OF THE POSSIBILITY OF SUCH DAMAGE.  
//

#include "FusionWare\Utilities.h"

using namespace FusionWare;

static void itoa10(int n,char s[])
{
    int i = 0;

    // Get absolute value of number
    unsigned int val = (unsigned int)((n < 0) ? -n : n);

    // Extract digits in reverse order
    do {
        s[i++] = (val % 10) + '0';
    } while (val /= 10);

    // Add sign if number negative
    if (n < 0) s[i++] = '-';

    s[i--] = '\0';

    // Reverse string
    for (n = 0; n < i; n++, i--)
    {
        char swap = s[n];
        s[n] = s[i];
        s[i] = swap;
    }
}

UINT16 FusionWare::Utilities::Sum(UINT16 seed, VOID *pData, UINT32 size)
{
    UINT32 sum;
    UINT16 *p;

    sum = seed;
    p = (UINT16*)pData;
    while( size >= sizeof(UINT16) )
    {
        sum += *p++;
        size -= sizeof(UINT16);
    }

    if(size > 0)
        sum += *((UINT8*)p);

    while( (sum & 0xFFFF0000) != 0 )
        sum = (sum & 0x0000FFFF) + (sum >> 16);

    return (UINT16)sum;
}


///////////////////////////////////////////////////////
// Description: 
//    Creates a Device Name for KITL Ethernet and EBOOT 
//    connectivity
//
// Input: 
//    MyAddr  MAC address
//    szBuf   Buffer to place the string into 
//
// Returns: 
//     void 
//     
// Remarks: 
//    Uses PlatformName and MyAddr to create a
//    unique name for the device.
//
void FusionWare::Utilities::CreateDeviceName(const EDBG_ADDR& MyAddr, char *szBuf, const char* PlatformName)
{
    int i;

    // leave enough room for "-XXXXX\0"
    for(i=0; PlatformName[i] && i < EDBG_MAX_DEV_NAMELEN-7; ++i)
       *szBuf++ = PlatformName[i];
    
    *szBuf++ = '-';

    itoa10(((MyAddr.wMAC[2]>>8) | ((MyAddr.wMAC[2] & 0x00ff) << 8)), szBuf);
}

///////////////////////////////////////////////////////
// Description: 
//    Dumps binary data to EdbgOutputDebugString
//
// Input: 
//    pData   The Data
//    Length  Length of the data
//
void FusionWare::Utilities::DumpData( const BYTE *pData, size_t Length )
{
    size_t i,j;

    // dump the data rows
    for( i = 0; i < Length / 16; i++ )
    {
        for( j = 0; j < 16; j++ )
            EdbgOutputDebugString( " %B", pData[i*16 + j] );
        EdbgOutputDebugString("   ");

        for( j = 0; j < 16; j++ )
            EdbgOutputDebugString( "%c", Utilities::PrintChar(pData[i*16 + j]));

        EdbgOutputDebugString( "\n" );
    }

    // take care of any partial row data left
    for( j = 0; j < 16; j++ )
    {
        if(j < Length % 16)
            EdbgOutputDebugString( " %B", pData[i*16 + j] );
        else
            EdbgOutputDebugString("   ");
    }
    EdbgOutputDebugString("   ");
    for( j = 0; j < Length % 16; j++ )
        EdbgOutputDebugString( "%c", Utilities::PrintChar(pData[i*16 + j]));

    EdbgOutputDebugString("\n" );
}

///////////////////////////////////////////////////////
// Description: 
//    Debug dump of an Ethernet frame
//
// Input: 
//    *pFrame     - Pointer to Ethernet frmae to display
//    FrameLength - Length of the frame
//
void FusionWare::Utilities::DumpEtherFrame( const BYTE *pFrame, WORD cwFrameLength )
{
    EdbgOutputDebugString( "Frame Buffer Address: 0x%X\r\n", pFrame );
    EdbgOutputDebugString( "To: %02X:%02X:%02X:%02X:%02X:%02X  From: %02X:%02X:%02X:%02X:%02X:%02X  Type: 0x%H  Length: %u\r\n",
        pFrame[0], pFrame[1], pFrame[2], pFrame[3], pFrame[4], pFrame[5],
        pFrame[6], pFrame[7], pFrame[8], pFrame[9], pFrame[10], pFrame[11],
        ntohs(*((UINT16 *)(pFrame + 12))), cwFrameLength );

    DumpData(pFrame, cwFrameLength);
}

